package Class;

/*
* Class类
* 除了int等基本类型外，Java的其他类型全部都是class（包括interface）。
* 而class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时，将其加载进内存。
* 每加载一种class，JVM就为其创建一个Class类型的实例，并关联起来。注意：这里的Class类型是一个名叫Class的class。它长这样：
* public final class Class {
    private Class() {}
  }
* 以String类为例，当JVM加载String类时，它首先读取String.class文件到内存，然后，为String类创建一个Class实例并关联起来：
* Class cls = new Class(String);
* 由于JVM为每个加载的class创建了对应的Class实例，并在实例中保存了该class的所有信息，包括类名、包名、父类、实现的接口、所有方法、字段等，因此，如果获取了某个Class实例，我们就可以通过这个Class实例获取到该实例对应的class的所有信息。
* 这种通过Class实例获取class信息的方法称为反射（Reflection）。
*
* */
public class Class {
    public static void main(String[] args) {
        classDemo();
    }

    private static void classDemo(){
        //获取一个class的Class实例,有三种方法
        //1:直接通过一个class的静态变量class获取:
        java.lang.Class<String> cls1 = String.class;
        System.out.println(cls1);//class java.lang.String
        //2:如果我们有一个实例变量，可以通过该实例变量提供的getClass()方法获取
        String s = "Hello";
        java.lang.Class<? extends String> cls2 = s.getClass();
        System.out.println(cls2);//class java.lang.String
        //3:如果知道一个class的完整类名，可以通过静态方法Class.forName()获取：
//        Class cls1 = Class.forName("java.lang.String");

        //因为Class实例在JVM中是唯一的，所以，上述方法获取的Class实例是同一个实例。可以用==比较两个Class实例：
        boolean sameClass = cls1 == cls2;
        System.out.println(sameClass);//true

//        注意一下Class实例比较和instanceof的差别:
        Integer n = 123;

        boolean b3 = n instanceof Integer;
        boolean b4 = n instanceof Number;

        boolean b1 = n.getClass() == Integer.class;
//        boolean b2 = n.getClass() == Number.class;

        System.out.println(b3);//true
        System.out.println(b4);//true
        System.out.println(b1);//true
//        System.out.println(b2);//false
        //用instanceof不但匹配当前类型，还匹配当前类型的子类。而用==判断class实例可以精确地判断数据类型，但不能作子类型比较。
        //通常情况下，我们应该用instanceof判断数据类型，因为面向抽象编程的时候，我们不关心具体的子类型。只有在需要精确判断一个类型是不是某个class的时候，我们才使用==判断class实例。
    }

    private static void printClassInfo(Class cls){
        //因为反射的目的是为了获得某个实例的信息。因此，当我们拿到某个Object实例时，我们可以通过反射获取该Object的class信息：
//        System.out.println("Class name: " + cls.getName());
    }



}
